import os
import sys
import winreg
import subprocess
from PyQt6.QtWidgets import QSystemTrayIcon, QMenu, QApplication
from PyQt6.QtGui import QIcon, QAction
from PyQt6.QtCore import QObject, pyqtSignal

class SystemIntegration(QObject):
    """Windows系统集成功能类"""
    
    # 信号定义
    show_window = pyqtSignal()
    hide_window = pyqtSignal()
    quit_application = pyqtSignal()
    
    def __init__(self, main_window):
        super().__init__()
        self.main_window = main_window
        self.tray_icon = None
        self.app_path = sys.executable if getattr(sys, 'frozen', False) else sys.argv[0]
        self.app_name = "GoFile"
        
        # 支持的文件类型
        self.supported_extensions = [
            # 图片文件
            '.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.tif', '.webp', '.ico',
            # 文本文件
            '.txt', '.md', '.markdown', '.rst', '.log', '.ini', '.conf', '.config',
            '.json', '.xml', '.yaml', '.yml', '.csv', '.tsv',
            # 代码文件
            '.py', '.js', '.jsx', '.ts', '.tsx', '.html', '.htm', '.css', '.scss',
            '.sass', '.less', '.php', '.rb', '.java', '.cpp', '.c', '.h', '.hpp',
            '.cs', '.go', '.rs', '.swift', '.kt',
            # 文档文件
            '.pdf', '.docx', '.doc', '.xlsx', '.xls', '.pptx', '.ppt',
            '.epub', '.mobi', '.azw', '.azw3',
            # 音频文件
            '.mp3', '.wav', '.ogg', '.flac', '.aac', '.m4a', '.wma',
            # 视频文件
            '.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.webm', '.m4v'
        ]
    
    def setup_system_tray(self):
        """设置系统托盘"""
        if not QSystemTrayIcon.isSystemTrayAvailable():
            return False
        
        # 创建托盘图标
        self.tray_icon = QSystemTrayIcon(self.main_window)
        
        # 设置图标
        icon = self.main_window.windowIcon()
        if icon.isNull():
            # 如果没有图标，创建一个默认图标
            icon = QIcon()
            icon.addPixmap(self.main_window.create_app_icon())
        self.tray_icon.setIcon(icon)
        
        # 创建托盘菜单
        tray_menu = QMenu()
        
        # 显示/隐藏窗口
        show_action = QAction("显示窗口", self.main_window)
        show_action.triggered.connect(self.show_main_window)
        tray_menu.addAction(show_action)
        
        hide_action = QAction("隐藏窗口", self.main_window)
        hide_action.triggered.connect(self.hide_main_window)
        tray_menu.addAction(hide_action)
        
        tray_menu.addSeparator()
        
        # 打开文件
        open_action = QAction("打开文件...", self.main_window)
        open_action.triggered.connect(self.main_window.open_file)
        tray_menu.addAction(open_action)
        
        tray_menu.addSeparator()
        
        # 退出应用
        quit_action = QAction("退出", self.main_window)
        quit_action.triggered.connect(self.quit_app)
        tray_menu.addAction(quit_action)
        
        self.tray_icon.setContextMenu(tray_menu)
        
        # 双击托盘图标显示/隐藏窗口
        self.tray_icon.activated.connect(self.tray_icon_activated)
        
        # 设置提示文本
        self.tray_icon.setToolTip("GoFile - 多媒体文件查看器")
        
        # 显示托盘图标
        self.tray_icon.show()
        
        return True
    
    def tray_icon_activated(self, reason):
        """托盘图标激活事件"""
        if reason == QSystemTrayIcon.ActivationReason.DoubleClick:
            if self.main_window.isVisible():
                self.hide_main_window()
            else:
                self.show_main_window()
    
    def show_main_window(self):
        """显示主窗口"""
        self.main_window.show()
        self.main_window.raise_()
        self.main_window.activateWindow()
        if self.main_window.isMinimized():
            self.main_window.showNormal()
    
    def hide_main_window(self):
        """隐藏主窗口"""
        self.main_window.hide()
    
    def quit_app(self):
        """退出应用程序"""
        if self.tray_icon:
            self.tray_icon.hide()
        QApplication.quit()
    
    def show_tray_message(self, title, message, icon=QSystemTrayIcon.MessageIcon.Information):
        """显示托盘消息"""
        if self.tray_icon and self.tray_icon.isVisible():
            self.tray_icon.showMessage(title, message, icon, 3000)
    
    def install_context_menu(self):
        """安装右键菜单到Windows资源管理器"""
        try:
            # 为每个支持的文件类型添加右键菜单
            for ext in self.supported_extensions:
                self._add_context_menu_for_extension(ext)
            
            # 添加文件夹右键菜单
            self._add_folder_context_menu()
            
            return True
        except Exception as e:
            print(f"安装右键菜单失败: {e}")
            return False
    
    def _add_context_menu_for_extension(self, extension):
        """为特定文件扩展名添加右键菜单"""
        try:
            # 打开或创建文件类型注册表项
            key_path = f"Software\\Classes\\{extension}"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, key_path) as key:
                pass
            
            # 添加shell命令
            shell_key_path = f"{key_path}\\shell\\GoFile"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, shell_key_path) as shell_key:
                winreg.SetValueEx(shell_key, "", 0, winreg.REG_SZ, "用GoFile打开")
                winreg.SetValueEx(shell_key, "Icon", 0, winreg.REG_SZ, f'"{self.app_path}",0')
            
            # 添加命令
            command_key_path = f"{shell_key_path}\\command"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, command_key_path) as command_key:
                winreg.SetValueEx(command_key, "", 0, winreg.REG_SZ, f'"{self.app_path}" "%1"')
                
        except Exception as e:
            print(f"为{extension}添加右键菜单失败: {e}")
    
    def _add_folder_context_menu(self):
        """添加文件夹右键菜单"""
        try:
            # 文件夹背景右键菜单
            key_path = "Software\\Classes\\Directory\\Background\\shell\\GoFile"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, key_path) as key:
                winreg.SetValueEx(key, "", 0, winreg.REG_SZ, "在此处打开GoFile")
                winreg.SetValueEx(key, "Icon", 0, winreg.REG_SZ, f'"{self.app_path}",0')
            
            command_key_path = f"{key_path}\\command"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, command_key_path) as command_key:
                winreg.SetValueEx(command_key, "", 0, winreg.REG_SZ, f'"{self.app_path}" "%V"')
            
            # 文件夹右键菜单
            folder_key_path = "Software\\Classes\\Directory\\shell\\GoFile"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, folder_key_path) as key:
                winreg.SetValueEx(key, "", 0, winreg.REG_SZ, "用GoFile打开")
                winreg.SetValueEx(key, "Icon", 0, winreg.REG_SZ, f'"{self.app_path}",0')
            
            folder_command_key_path = f"{folder_key_path}\\command"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, folder_command_key_path) as command_key:
                winreg.SetValueEx(command_key, "", 0, winreg.REG_SZ, f'"{self.app_path}" "%1"')
                
        except Exception as e:
            print(f"添加文件夹右键菜单失败: {e}")
    
    def uninstall_context_menu(self):
        """卸载右键菜单"""
        try:
            # 删除文件类型右键菜单
            for ext in self.supported_extensions:
                try:
                    key_path = f"Software\\Classes\\{ext}\\shell\\GoFile"
                    winreg.DeleteKey(winreg.HKEY_CURRENT_USER, f"{key_path}\\command")
                    winreg.DeleteKey(winreg.HKEY_CURRENT_USER, key_path)
                except FileNotFoundError:
                    pass
            
            # 删除文件夹右键菜单
            try:
                winreg.DeleteKey(winreg.HKEY_CURRENT_USER, "Software\\Classes\\Directory\\Background\\shell\\GoFile\\command")
                winreg.DeleteKey(winreg.HKEY_CURRENT_USER, "Software\\Classes\\Directory\\Background\\shell\\GoFile")
            except FileNotFoundError:
                pass
            
            try:
                winreg.DeleteKey(winreg.HKEY_CURRENT_USER, "Software\\Classes\\Directory\\shell\\GoFile\\command")
                winreg.DeleteKey(winreg.HKEY_CURRENT_USER, "Software\\Classes\\Directory\\shell\\GoFile")
            except FileNotFoundError:
                pass
            
            return True
        except Exception as e:
            print(f"卸载右键菜单失败: {e}")
            return False
    
    def set_file_associations(self):
        """设置文件关联"""
        try:
            # 创建应用程序注册表项
            app_key_path = f"Software\\Classes\\Applications\\{os.path.basename(self.app_path)}"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, app_key_path) as app_key:
                winreg.SetValueEx(app_key, "FriendlyAppName", 0, winreg.REG_SZ, self.app_name)
            
            # 添加shell命令
            shell_key_path = f"{app_key_path}\\shell\\open\\command"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, shell_key_path) as shell_key:
                winreg.SetValueEx(shell_key, "", 0, winreg.REG_SZ, f'"{self.app_path}" "%1"')
            
            # 为每个支持的文件类型设置关联
            for ext in self.supported_extensions:
                self._set_file_association(ext)
            
            return True
        except Exception as e:
            print(f"设置文件关联失败: {e}")
            return False
    
    def _set_file_association(self, extension):
        """为特定扩展名设置文件关联"""
        try:
            # 添加到OpenWithList
            open_with_key_path = f"Software\\Classes\\{extension}\\OpenWithList\\{os.path.basename(self.app_path)}"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, open_with_key_path) as key:
                pass
            
            # 添加到OpenWithProgids
            progid = f"GoFile{extension.replace('.', '').upper()}"
            progids_key_path = f"Software\\Classes\\{extension}\\OpenWithProgids"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, progids_key_path) as key:
                winreg.SetValueEx(key, progid, 0, winreg.REG_NONE, b'')
            
            # 创建ProgID
            progid_key_path = f"Software\\Classes\\{progid}"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, progid_key_path) as key:
                winreg.SetValueEx(key, "", 0, winreg.REG_SZ, f"{self.app_name} {extension.upper()} File")
                winreg.SetValueEx(key, "FriendlyTypeName", 0, winreg.REG_SZ, f"{extension.upper()} File")
            
            # 设置图标
            icon_key_path = f"{progid_key_path}\\DefaultIcon"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, icon_key_path) as key:
                winreg.SetValueEx(key, "", 0, winreg.REG_SZ, f'"{self.app_path}",0')
            
            # 设置打开命令
            command_key_path = f"{progid_key_path}\\shell\\open\\command"
            with winreg.CreateKey(winreg.HKEY_CURRENT_USER, command_key_path) as key:
                winreg.SetValueEx(key, "", 0, winreg.REG_SZ, f'"{self.app_path}" "%1"')
                
        except Exception as e:
            print(f"为{extension}设置文件关联失败: {e}")
    
    def remove_file_associations(self):
        """移除文件关联"""
        try:
            # 删除应用程序注册表项
            app_key_path = f"Software\\Classes\\Applications\\{os.path.basename(self.app_path)}"
            try:
                self._delete_registry_key_recursive(winreg.HKEY_CURRENT_USER, app_key_path)
            except FileNotFoundError:
                pass
            
            # 删除文件关联
            for ext in self.supported_extensions:
                self._remove_file_association(ext)
            
            return True
        except Exception as e:
            print(f"移除文件关联失败: {e}")
            return False
    
    def _remove_file_association(self, extension):
        """移除特定扩展名的文件关联"""
        try:
            # 从OpenWithList中移除
            try:
                open_with_key_path = f"Software\\Classes\\{extension}\\OpenWithList"
                with winreg.OpenKey(winreg.HKEY_CURRENT_USER, open_with_key_path, 0, winreg.KEY_ALL_ACCESS) as key:
                    try:
                        winreg.DeleteKey(key, os.path.basename(self.app_path))
                    except FileNotFoundError:
                        pass
            except FileNotFoundError:
                pass
            
            # 从OpenWithProgids中移除
            progid = f"GoFile{extension.replace('.', '').upper()}"
            try:
                progids_key_path = f"Software\\Classes\\{extension}\\OpenWithProgids"
                with winreg.OpenKey(winreg.HKEY_CURRENT_USER, progids_key_path, 0, winreg.KEY_ALL_ACCESS) as key:
                    try:
                        winreg.DeleteValue(key, progid)
                    except FileNotFoundError:
                        pass
            except FileNotFoundError:
                pass
            
            # 删除ProgID
            progid_key_path = f"Software\\Classes\\{progid}"
            try:
                self._delete_registry_key_recursive(winreg.HKEY_CURRENT_USER, progid_key_path)
            except FileNotFoundError:
                pass
                
        except Exception as e:
            print(f"移除{extension}文件关联失败: {e}")
    
    def _delete_registry_key_recursive(self, hkey, key_path):
        """递归删除注册表项"""
        try:
            with winreg.OpenKey(hkey, key_path, 0, winreg.KEY_ALL_ACCESS) as key:
                # 获取所有子项
                subkeys = []
                try:
                    i = 0
                    while True:
                        subkey_name = winreg.EnumKey(key, i)
                        subkeys.append(subkey_name)
                        i += 1
                except OSError:
                    pass
                
                # 递归删除子项
                for subkey_name in subkeys:
                    self._delete_registry_key_recursive(hkey, f"{key_path}\\{subkey_name}")
            
            # 删除当前项
            winreg.DeleteKey(hkey, key_path)
        except FileNotFoundError:
            pass
    
    def is_context_menu_installed(self):
        """检查右键菜单是否已安装"""
        try:
            key_path = "Software\\Classes\\.txt\\shell\\GoFile"
            with winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path):
                return True
        except FileNotFoundError:
            return False
    
    def is_file_association_set(self):
        """检查文件关联是否已设置"""
        try:
            app_key_path = f"Software\\Classes\\Applications\\{os.path.basename(self.app_path)}"
            with winreg.OpenKey(winreg.HKEY_CURRENT_USER, app_key_path):
                return True
        except FileNotFoundError:
            return False